Http with iziBasic and PP
Thursday 26 October 2006 - 11:27:59
Yes i use now a lot ppcompiler,
but i ven't forgotten iziBasic, the first language i ve used to create my own
application. Here you will find an article about how to make http request with
iziBasic and an pp applet.
Needed
The PP Applet (Pascal)
Two choices are avaible :
So we will see the second choice.
Here the source code of the applet.
Nothing is difficult, only an access to an api we can't reach with iziBasic.
For more information about the netlib connection read my other paper about pp and socket.
The iziBasic code Now i ll show you how to use our applet.
Conclusion
Now all is possible ...
Needed
- PPShell
- pp.exe for ARM
- iziBasic
- Knowledge about compilation with PP
- Knowledge about compilation with iziBasic
The PP Applet (Pascal)
Two choices are avaible :
- Return the result of the http request with the string response of the applet. But string are limited to 64 character.
- Write the result of the http request in a palm file to use it entirely in
iziBasic.
So we will see the second choice.
Here the source code of the applet.
program iBHttpPP;
//
type iBasFunType=function(S:string):string;
var iBasCallPP:iBasFunType;
const
MAXMEGASTRING=16376;
//PP limits arrays to 32 k ... this one is one of the biggest you can create
// soit MAXMEGASTRING=32752;
type
u_char=UInt8;
u_short=UInt16;
u_int=UInt16;
u_long=UInt32;
size_t=UInt32;
MegaStringPtr = ^MegaStringType;
MegaStringType = Array[0..MAXMEGASTRING] of char;
const
SOCK_STREAM=netSocketTypeStream;
SOCK_DGRAM=netSocketTypeDatagram;
SOCK_RAW=netSocketTypeRaw;
SOCK_RDM=netSocketTypeReliableMsg;
AF_INET=netSocketAddrINET;
AF_RAW=netSocketAddrRaw;
type
sockaddr=record
sa_family: Int16;
sa_data: array[1..14] of UInt8;
end;
in_addr=record
case integer of
1:( s_net, s_host, s_lh, s_impno: UInt8; );
2:( s_W1, s_imp: UInt16; );
3:( s_addr: UInt32 );
end;
sockaddr_in=record
sin_family: Int16;
sin_port: u_short;
sin_addr: in_addr;
sin_zero: array[1..8] of char;
end;
/////////////////////////////////////
// StringToRessourceLab
/////////////////////////////////////
function StringToRessourceLab(const sMyString:string):integer;
begin
StringToRessourceLab:=
Ord(sMyString[4])+
256*Ord(sMyString[3])+
65536*Ord(sMyString[2])+
16777216*Ord(sMyString[1]);
end;
/////////////////////////////////////
// charcpy
// procedure to copy a string in
// the megastring buffer
/////////////////////////////////////
procedure charcpy(var index:UInt16;c:MegaStringPtr;s:String);
var
i:UInt32;
begin
i:=1;
while (s[i]<>chr(0)) and (index
c^[index]:=s[i];
index:=index+1;
i:=i+1;
end;
if index>MAXMEGASTRING then
index:=MAXMEGASTRING;
end;
/////////////////////////////////////
// CreateDb
// Funtion to create a palm data database
/////////////////////////////////////
Function CreateDb(resName,resCreator,rType:string):Err;
var
CardNumber:integer;
DBErr:Err;
libCreatorID:Uint32;
IDDataBase:LocalID;
Begin
CardNumber:=0;
IDDataBase:=DmFindDatabase(0,resName);
if (IDDataBase=0) then
DBErr := DmCreateDatabase(CardNumber, resName,StringToRessourceLab(resCreator),StringToRessourceLab(rType), false);
CreateDb:=DBErr;
end;
/////////////////////////////////////
// DelDb
// Function to del a palm database
/////////////////////////////////////
Procedure DelDb(resName:string);
var
CardNumber:integer;
DBErr:Err;
IDDataBase:localID;
Begin
CardNumber:=0;
IDDataBase:=DmFindDatabase(0,resName);
if (IDDataBase>0) then
DBErr := DmDeleteDatabase(CardNumber, IDDataBase);
end;
/////////////////////////////////////
// WriteHTTP
// Function to write the megastring
// buffer to a palm database
/////////////////////////////////////
procedure WriteHTTP(fichier:String;s:MegaStringPtr;size:UInt32);
var
h:Memhandle;
pp:Pointer;
u:UInt16;
e:Err;
gDataBase:DmOpenRef;
IDDataBase:LocalID;
begin
IDDataBase:=DmFindDatabase(0,fichier);
if (IDDataBase<>0) then Begin
gDataBase:=DmOpenDatabase(0,IDDataBase,dmModeReadWrite);
if (gDataBase<>nil) then begin
if DmNumRecords(gDataBase)<65000 then begin
u:=0; // new record
h:=DmNewRecord(gDataBase,u,size);
if h<>nil then begin
pp:=MemHandleLock(h);
if pp <> nil then begin
DmWrite(pp,0,s,size);
DmReleaseRecord(gDataBase,u,true);
MemHandleUnlock(h); // PG 22022004
end;
end;
end;
DmCloseDatabase(gDataBase);
end;
end;
end;
/////////////////////////////////////
// getbyname
// The main function of the applet.
// Here is constructed the http
// request, sent, and after we read
// the answer to write it to a file
/////////////////////////////////////
function getbyname(fichier:string;domain:string;page:String;port:UInt16):String;
var
size,received:UInt16;
refsocket:NetSocketRef;
address:NetSocketAddrType;
address_in:NetSocketAddrINType;
address_inaddrPtr:Pointer;
host:NetHostInfoBufType;
requetehttp:MegaStringPtr;
indexrequetehttp:UInt16;
endline:string;
libRef:UInt16;
error:UInt16;
erreur:Err;
y,nb:UInt16;
AppNetTimeout: Int32;
AppNetRefnum: UInt16;
sent:UInt16;
saved:WinHandle;
begin
AppNetRefnum:=0;
error:=0;
//Recherche de la netlib
SysLibFind('Net.lib',AppNetRefnum);
//Set timeout
AppNetTimeout:=30*100;
//Init of the megastring buffer
requetehttp:=MemPtrNew(sizeof(char)*MAXMEGASTRING);
//Test if buffer is correctly initializing.
if requetehttp=nil then begin
error:=1;
getbyname:='Error in memory allocating ...';
end;
//Si le buffer est bien initialise alors nous attaquons
if error=0 then begin
//Opening netlib
erreur:=NetLibOpen(AppNetRefnum,error);//,error);
//If it s ok ... so
if (error=0) or (error=$1201) then begin
//We ask the ip of the hostname to the dns.
NetLibGetHostByName(AppNetRefnum, domain,@host,AppNetTimeout,error);
//We forge the socket
refsocket:=NetLibSocketOpen(AppNetRefnum,netSocketAddrINET,netSocketTypeStream,6,AppNetTimeout,error);
if refsocket<>0 then begin
address_in.addr:=host.address[0];
address_in.family:= 2;
address_in.port:=port;
//Connecting socket
error:=NetLibSocketConnect(AppNetRefnum,refsocket,@address_in,sizeof(address_in),AppNetTimeout,erreur);
if erreur=0 then begin
//Forge de la requete http
endline:=CHR(13)+CHR(10);
indexrequetehttp:=0;
charcpy(indexrequetehttp,requetehttp,'GET '+page);
charcpy(indexrequetehttp,requetehttp,' HTTP/1.1'+endline+'host: '+domain+endline);
charcpy(indexrequetehttp,requetehttp,'Connection: close'+endline);
charcpy(indexrequetehttp,requetehttp,'User-Agent: Palm'+endline);
charcpy(indexrequetehttp,requetehttp,endline);
//We send the request until all is sent or an error occur
sent:=0;
error:=1;
while (sent0) and (erreur=0) do begin
error:=NetLibSend(AppNetRefnum,refsocket,@requetehttp^[sent],indexrequetehttp-sent,0,nil,0,AppNetTimeout,erreur);
sent:=sent+error;
end;
//if nothing is sent then error occurs
if sent<=0 then getbyname:='Error while sending...';
//We read answer in the netlib buffer until the buffer is clear
error:=1;
erreur:=0;
sent:=0;
while (error>0) and ((MAXMEGASTRING-sent)>1) and (erreur=0) do begin
error:=NetLibReceive(AppNetRefnum,refsocket,@requetehttp^[sent],(MAXMEGASTRING-sent),0,nil,nil,AppNetTimeout,erreur);
sent:=sent+error;
end;
//We del the file
DelDb(fichier);
//We create a new palm database
CreateDb(fichier,('Khrt'),('http'));
//We write the result of the request
WriteHTTP(fichier,requetehttp,sent);
end else begin
getbyname:='Can t open socket';
end;
NetLibSocketClose(AppNetRefnum, refsocket,AppNetTimeout,erreur);
end else begin
getbyname:='Can t create socket';
end;
NetLibClose(AppNetRefnum,0);
end else begin
getbyname:='Can t open netlib';
end;
end;
MemPtrFree(requetehttp);
end;
//Fonction appele par iziBasic lors d un CallPP
function CallPP(S:string):string;
var
url,fichier,domain,page,port:String;
i,u:UInt16;
begin
url:='';
fichier:='';
domain:='';
page:='';
port:='';
i:=1;
u:=0;
//Tokenize of the iziBasic call parameter string
// le fichier
// le domaine
// la page
// le port
while (S[i]<>CHR(0)) and (i<=64) do begin
if (S[i]<>CHR(10)) then begin
case u of
0: begin fichier:=fichier+S[i]; end;
1: begin url:=url+S[i]; end;
2: begin port:=port+S[i]; end;
end;
end else begin
u:=u+1;
end;
i:=i+1;
end;
i:=1;
u:=0;
while (url[i]<>CHR(0)) and (i<=64) do begin
if (url[i]<>'/') then begin
if u=0 then begin
domain:=domain+url[i];
end else begin
page:=page+url[i];
end;
end else begin
u:=1;
page:=page+url[i];
end;
i:=i+1;
end;
CallPP:=getbyname(fichier,domain,page,StrAToI(port));
// CallPP:=port;
end;
begin
iBasCallPP:=CallPP;
end.
Nothing is difficult, only an access to an api we can't reach with iziBasic.
For more information about the netlib connection read my other paper about pp and socket.
The iziBasic code Now i ll show you how to use our applet.
' iBHttpPP.ibas
BEGIN
LABEL #1,"Fichier : TESTHTTP",2,30
LABEL #2,"URL : khertan.net/index.php",2,40
LABEL #3,"Port : 80",2,50
REM The parameter string
REM The file (here : TESTHTTP)
REM CHR$(10)
REM URL (here : khertan.net/index.php)
REM CHR$(10)
REM The port : (here : 80)
R$="TESTHTTP"+CHR$(10)+"khertan.net/index.php"+CHR$(10)+"80"
A$=CALLPP$(100,R$)
A=FILEERROR
IF A=0 THEN
A$="PP Code replied: '"+A$+"'"
ELSE
A$="PP Code was not found!"
ENDIF
LABEL #4,A$,2,80
REPEAT : A=DOEVENTS : UNTIL A=-1
END
Conclusion
Now all is possible ...